package gui;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Hashtable;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * Initial GUI window for Menagerie project.
 * Current version intended a demonstration only. Final version will be tied into the
 * rest of the system, allowing management functions to be performed using a graphical
 * interface.
 * 
 * @author Charlie Greenbacker
 * @author <a href="mailto:charlieg@cis.udel.edu">charlieg@cis.udel.edu</a>
 * @author <a href="http://www.cis.udel.edu/~charlieg">www.cis.udel.edu/~charlieg</a>
 * @version 1.0, &nbsp; 23 Sept 2010
 * 
 */
public class ProfileWindow extends JPanel implements ActionListener {
	// satisfies Eclipse warning about serializable classes
	private static final long serialVersionUID = -6363287631888885766L;
	
	// drop-down lists to contain animal groups
	// Note: defined here instead of inside ProfileWindow constructor
	// so that we can modify them directly from the action listener
	private JComboBox firstCombo;
	private JComboBox secondCombo;
	private JComboBox speciesCombo;
	private JComboBox specimenCombo;
	
	// animal groups for the dynamic drop-down lists
	// TODO: automatically generate these lists from Menagerie inventory
	String[] animals = {"Please Select:", "Bird", "Mammal", "Reptile"};
	String[] birds = {"Please Select:", "Raptor", "Ratite"};
	String[] mammals = {"Please Select:", "Marsupial", "Ungulate"};
	String[] reptiles = {"Please Select:", "Lizard", "Snake"};
	String[] raptors = {"Please Select:", "Andean Condor", "Brown Falcon"};
	String[] ratites = {"Please Select:", "Emu", "Ostrich"};
	String[] marsupials = {"Please Select:", "Red Kangaroo", "Koala"};
	String[] ungulates = {"Please Select:", "Giraffe", "Fin Whale"};
	String[] lizards = {"Please Select:", "Carolina Anole", "Green Iguana"};
	String[] snakes = {"Please Select:", "Diamond Python", "Milk Snake"};
	String[] kangaroos = {"Please Select:", "Kanga", "Roo", "Joey"};
	
	// stores group lists for easy lookup
	private Hashtable<String, String[]> subItems = new Hashtable<String, String[]>();
	
	// temporary placeholder for detailed editable profile information
	private JLabel profileLabel;
	
	/**
	 * Sole constructor for ProfileWindow class.
	 * Sets layout and arranges various components for GUI.
	 */
	public ProfileWindow() {
		super(new GridBagLayout());
		
        GridBagConstraints c = new GridBagConstraints(); // settings for individual components
        Insets gridPadding = new Insets(6, 6, 6, 6); // external padding between components
        
        // set up leftmost drop-down list with top-level animal grouping
		firstCombo = new JComboBox(animals); // initialized with top-level group list
		firstCombo.setPrototypeDisplayValue("XXXXXXXXXXXX"); // otherwise, tiny before filled
		c.gridx = 0; // column position
		c.gridy = 0; // row position
		c.insets = gridPadding; // external padding
        add(firstCombo, c); // add to window panel
        firstCombo.addActionListener(this); // listens for action events (click & select)

        // set up remaining drop-down lists, which get filled-out dynamically
		secondCombo = new JComboBox(); // initialized as empty, updated dynamically by action listener
		secondCombo.setPrototypeDisplayValue("XXXXXXXXXXXX");
		c.gridx = 1;
		c.gridy = 0;
		c.insets = gridPadding;
        add(secondCombo, c);
        secondCombo.addActionListener(this);

		speciesCombo = new JComboBox();
		speciesCombo.setPrototypeDisplayValue("XXXXXXXXXXXX");
		c.gridx = 2;
		c.gridy = 0;
		c.insets = gridPadding;
        add(speciesCombo, c);
        speciesCombo.addActionListener(this);

		specimenCombo = new JComboBox();
		specimenCombo.setPrototypeDisplayValue("XXXXXXXXXXXX");
		c.gridx = 3;
		c.gridy = 0;
		c.insets = gridPadding;
        add(specimenCombo, c);
        specimenCombo.addActionListener(this);
        
        // TODO: (optional) the above code is repetitive... can you improve it?
        
        // set up temporary placeholder for profile data
        profileLabel = new JLabel("Profile information goes here");
		c.gridx = 0;
		c.gridy = 1; // put this in the second row
		c.insets = gridPadding;
		c.ipady = 350; // temporary, makes it tall to fill out window
        c.gridwidth = 4; // span complete row below buttons
        add(profileLabel, c);

        // add each named array to hashtable, indexed by parent group
        // TODO: add the automatically-generated lists instead (see first TODO)
		subItems.put(animals[1], birds);
		subItems.put(animals[2], mammals);
		subItems.put(animals[3], reptiles);
		subItems.put(birds[1], raptors);
		subItems.put(birds[2], ratites);
		subItems.put(mammals[1], marsupials);
		subItems.put(mammals[2], ungulates);
		subItems.put(reptiles[1], lizards);
		subItems.put(reptiles[2], snakes);
		subItems.put(marsupials[1], kangaroos);
	}
	
	/**
	 * Creates GUI window.
	 */
	private static void createAndShowGUI() {
        // set up window
        JFrame frame = new JFrame("ProfileWindow");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // set up content pane
        JComponent newContentPane = new ProfileWindow();
        frame.setContentPane(newContentPane);
        
        // show window
        frame.pack();
        frame.setVisible(true);
	}
	
	/**
	 * Temporary main method used to demonstrate GUI.
	 * TODO: Remove this and have the Controller invoke the GUI instead.
	 * 
	 * @param args (unused)
	 */
	public static void main(String[] args) {
		createAndShowGUI();
	}

	/**
	 * Dynamically updates drop-down lists according to selection.
	 * When a selection is made in one of the drop-down lists, this method
	 * determines the source of the event (which drop-down list was clicked
	 * on) and updates the contents of the subordinate lists as appropriate.
	 * 
	 * TODO: (optional) this code is repetitive & ugly... can you improve it?
	 * 
	 * @param e ActionEvent triggering invocation of this method
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == firstCombo) { // find source of event
			// get currently selected item
			String item = (String)firstCombo.getSelectedItem();
			// make sure a valid selection was made
			if ((item == null) || (item.equals("Please Select:"))) {
				// reset next drop-down list & profile information
				secondCombo.setModel(new DefaultComboBoxModel());
				profileLabel.setText("Profile information goes here");
			} else { // valid selection made, update subordinate lists
				// lookup items for next grouping in hashtable
				String[] group = subItems.get(item);
				// populate next drop-down lists with these items
				secondCombo.setModel(new DefaultComboBoxModel(group));
				// update profile section with information for this group
				profileLabel.setText("Some information about: " + item);
			}
			speciesCombo.setModel(new DefaultComboBoxModel());
			specimenCombo.setModel(new DefaultComboBoxModel());
		} else if (e.getSource() == secondCombo) {
			String item = (String)secondCombo.getSelectedItem();
			if ((item == null) || (item.equals("Please Select:"))) {
				speciesCombo.setModel(new DefaultComboBoxModel());
				profileLabel.setText("Some information about: " + (String)firstCombo.getSelectedItem());
			} else {
				String[] group = subItems.get(item);
				speciesCombo.setModel(new DefaultComboBoxModel(group));
				profileLabel.setText("Some information about: " + item);
			}
			specimenCombo.setModel(new DefaultComboBoxModel());
		} else if (e.getSource() == speciesCombo) {
			String item = (String)speciesCombo.getSelectedItem();
			if ((item == null) || (item.equals("Please Select:"))) {
				specimenCombo.setModel(new DefaultComboBoxModel());
				profileLabel.setText("Some information about: " + (String)secondCombo.getSelectedItem());
			} else {
				// TODO: remove & replace the following temporary conditional
				if (item.equals("Red Kangaroo")) { // so far, the only species we have specimens for
					String[] group = subItems.get(item);
					specimenCombo.setModel(new DefaultComboBoxModel(group));
					profileLabel.setText("Some information about: " + item);
				} else { // temporarily inform user that there are no specimens to display
					specimenCombo.setModel(new DefaultComboBoxModel());
					profileLabel.setText("No specimens available for this Species.");
				}
			}
		} else if (e.getSource() == specimenCombo) { // display information about individual specimen
			String item = (String)specimenCombo.getSelectedItem();
			if (item != null) {
				profileLabel.setText("Some information about: " + item);
			}
		} else {
			// uh oh!
		}
	}
}
